/*
写一个 定时器 类，想实现心跳机制
*/
#include <time.h>
#include <unistd.h>

#include <atomic>
#include <functional>
#include <iostream>
#include <queue>
#include <vector>
typedef std::function<void()> TimerCallback;

/*
在网络库或者我的http服务器项目中，使用定时器的逻辑如下：

while(condition){
    1. 检测定时器
    2. 执行I/O多路复用技术
    3. 处理事件（读或者写事件）
    4. 处理其他事件（如果有的话）
}
*/

class MyTimer {
public:
    // 构造函数
    MyTimer() {}
    MyTimer(int32_t rpt, int64_t interval, const TimerCallback &callback);
    // 定时时间到，如何处理？
    void run() {
        // 调用回调函数进行作出反应动作
        m_callback();
    }
    // 生成全局唯一的定时器id方法
    static int64_t generateID();
    static std::atomic<int64_t> m_initialID;

    // 对外接口
    int64_t getExpiredTime() const { return m_expiredTime; }

private:
    // 定时器id
    int64_t m_id;
    // 定时器次数
    int32_t m_repeatedTimes;
    // 过期时间
    int64_t m_expiredTime;
    // 过期时间间隔
    int64_t m_interval;
    // 回调函数
    TimerCallback m_callback;
};

// 定时器管理类
class MyTimerManager {
public:
private:
    class MyCmp {
    public:
        bool operator()(const MyTimer *lhs, const MyTimer *rhs) {
            return lhs->getExpiredTime() > rhs->getExpiredTime();
        }
    };
    // 可以使用链表、小根堆这两个数据结构对定时器进行存储和管理
    std::priority_queue<MyTimer *, std::vector<MyTimer *>, MyCmp> m_que;
};

// 对static的原子变量进行初始化
std::atomic<int64_t> MyTimer::m_initialID(0);

// 类外定义方法
int64_t MyTimer::generateID() {
    int64_t tmpID = static_cast<int64_t>(m_initialID++);
    return tmpID;
}

// 构造函数
MyTimer::MyTimer(int32_t rpt, int64_t interval, const TimerCallback &callback) {
    m_repeatedTimes = rpt;
    m_interval = interval;
    m_expiredTime = (int64_t)time(nullptr) + m_interval;
    m_callback = callback;
    m_id = MyTimer::generateID();
}